﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using JasLib.Extensions;
using Microsoft.Win32.SafeHandles;

namespace JasLib.Interop.Win32
{
    public static partial class WINHTTP
    {
        [DllImport(Constants.ModuleNames.WINHTTP, EntryPoint = "WinHttpCloseHandle", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Winapi, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool WinHttpCloseHandle([In] HINTERNET hInternet);

        [DllImport(Constants.ModuleNames.WINHTTP, EntryPoint = "WinHttpGetProxyForUrl", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Winapi, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool WinHttpGetProxyForUrl(
            [In] HINTERNET hSession,
            [In, MarshalAs(UnmanagedType.LPWStr)] string lpcwszUrl,
            [In] ref WINHTTP_AUTOPROXY_OPTIONS pAutoProxyOptions,
            [Out] out WINHTTP_PROXY_INFO.Flat pProxyInfo);

        /// <summary>
        /// Safe overload for the Win32 WinHttpGetProxyForUrl function that throws an exception on failure.
        /// </summary>
        public static void WinHttpGetProxyForUrl(
            HINTERNET hSession,
            string lpcwszUrl,
            ref WINHTTP_AUTOPROXY_OPTIONS pAutoProxyOptions,
            out WINHTTP_PROXY_INFO.Managed pProxyInfo)
        {
            WINHTTP_PROXY_INFO.Flat flatProxyInfo;
            if (!WinHttpGetProxyForUrl(hSession, lpcwszUrl, ref pAutoProxyOptions, out flatProxyInfo))
                throw new Win32Exception();

            try
            {
                pProxyInfo = new WINHTTP_PROXY_INFO.Managed
                {
                    dwAccessType = flatProxyInfo.dwAccessType,
                    lpszProxy = Marshal.PtrToStringUni(flatProxyInfo.lpszProxy).Split(ch => char.IsWhiteSpace(ch) || ch == ';').ToArray(),
                    lpszProxyBypass = Marshal.PtrToStringUni(flatProxyInfo.lpszProxyBypass).Split(ch => char.IsWhiteSpace(ch) || ch == ';').ToArray(),
                };
            }
            finally
            {
                KERNEL32.GlobalFree(flatProxyInfo.lpszProxy);
                KERNEL32.GlobalFree(flatProxyInfo.lpszProxyBypass);
            }
            return;
        }

        [DllImport(Constants.ModuleNames.WINHTTP, EntryPoint = "WinHttpOpen", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Winapi, SetLastError = true)]
        public static extern HINTERNET WinHttpOpen(
            [In, MarshalAs(UnmanagedType.LPWStr)] string pwszUserAgent,
            [In] WinHttpProxyAccessType dwAccessType,
            [In, MarshalAs(UnmanagedType.LPWStr)] string pwszProxyName,
            [In, MarshalAs(UnmanagedType.LPWStr)] string pwszProxyBypass,
            [In] uint dwFlags);
    }
}
